package haders

import (
	"context"
	"encoding/json"
	"fmt"
	"log/slog"

	"torrent/models"

	"net/http"

	"github.com/alexedwards/scs/v2"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

var cong = &oauth2.Config{
	ClientID:     "508071792178-0bc98o9km9hpfmobcgltnl56j0ahn3ia.apps.googleusercontent.com",
	ClientSecret: "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",
	RedirectURL:  "http://localhost:8000/auth/callback",
	Scopes:       []string{"email", "profile"},
	Endpoint:     google.Endpoint,
}

type Dao interface {
	CheckUserReg(user models.UserGoogle) (bool, error)
	InsertUser(user models.UserGoogle) error
	Insertfavorite(f models.Favorite) (string, error)
}

func googleHandler(Log *slog.Logger) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		url := cong.AuthCodeURL("state", oauth2.AccessTypeOffline)
		const op = "GET./auth/login/google"
		Log.Debug(op, slog.String("url", url))
		http.Redirect(w, r, url, http.StatusTemporaryRedirect)
	}

}
func googleCallbackHandler(log *slog.Logger, pool Dao, sesion *scs.SessionManager) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		code := r.URL.Query().Get("code")
		t, err := cong.Exchange(context.Background(), code)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		client := cong.Client(context.Background(), t)
		resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
		if err != nil {
			const op = "GET oauth2/v2/userinfo"
			log.Error(op, err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		defer resp.Body.Close()

		var v models.UserGoogle

		err = json.NewDecoder(resp.Body).Decode(&v)
		if err != nil {
			const op = "json NewDecoder"
			log.Error(op, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if v.VerifiedEmail {
			if b, err := pool.CheckUserReg(v); err != nil {
				log.Error("db user : err", err)
				if err = pool.InsertUser(v); err != nil {
					const op = "insertUser op"
					log.Error(op, err)
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				if b {
					sesion.Put(r.Context(), "email", v.Email)
					http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
				}
			}
			sesion.Put(r.Context(), "email", v.Email)
			http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		}
	}
}

func dashboard(sesion *scs.SessionManager, log *slog.Logger) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		email := sesion.GetString(r.Context(), "email")
		if email == "" {
			log.Info("email nil", slog.String("email", email))
			http.Redirect(w, r, "/auth/login/google", http.StatusTemporaryRedirect)
			return
		}
		log.Debug("email", slog.String("email", email))

	}
}

func reg(sesion *scs.SessionManager, log *slog.Logger, pool Dao) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var v models.UserGoogle
		if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
			const op = "json NewDecoder"
			log.Error(op, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		r.Body.Close()
		if err := pool.InsertUser(v); err != nil {
			const op = "insertUser op"
			log.Error(op, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		sesion.Put(r.Context(), "email", v.Email)
	}
}

func home(sesion *scs.SessionManager, log *slog.Logger, pool Dao) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		email := sesion.GetString(r.Context(), "email")
		if email == "" {
			log.Info("email nil", slog.String("email", email))
			http.Redirect(w, r, "/auth/login/google", http.StatusTemporaryRedirect)
			return
		}
		var favorite models.Favorite
		if err := json.NewDecoder(r.Body).Decode(&favorite); err != nil {
			const op = "json NewDecoder"
			log.Error(op, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		v, err := pool.Insertfavorite(favorite)
		if err != nil {
			log.Info("error", err)
			http.Error(w, "пользователь не вставлен", http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, v)
	}
}
